﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ATest.Tests.MockObjects;
using ATest.Controllers;
using System.Web.Mvc;
using System.Web.Routing;
using ATest.Bll;

namespace ATest.Tests.ControllerTests
{
    [TestClass]
    public class QuestionControllerTest : BaseControllerTest
    {
        private List<MockTest> _TestData;
        private List<MockQuestion> _QuestionData;
        private MockQuestionRepository _QuestionRepository;
        private MockTestRepository _TestRepository;
        private QuestionController _QuestionController;

        protected override void Initalise()
        {
            _TestData = MockTest.CreateList(2);
            _QuestionData = MockQuestion.CreateList(10);

            _TestData.ForEach(test => test.SetQuestions(_QuestionData.Where((question, i) => i % _TestData.Count == _TestData.IndexOf(test)).Select(question => question.Object)));
            _QuestionData.ForEach(question => question.SetTest(_TestData[_QuestionData.IndexOf(question) % _TestData.Count].Object));

            _QuestionRepository = new MockQuestionRepository(_QuestionData.Select(x => x.Object));
            _TestRepository = new MockTestRepository(_TestData.Select(x => x.Object));

            _QuestionController = new QuestionController(_QuestionRepository.Object, _TestRepository.Object);

            _QuestionController.ControllerContext = new System.Web.Mvc.ControllerContext(_MockHttpContext.Object, new RouteData(), _QuestionController);
        }

        [TestMethod]
        public void Index_WithInvalidTestId_Returns_NotFound()
        { 
            var result = _QuestionController.Index(int.MaxValue, false) as ViewResult;
            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Index_WithValidTestId_Returns_View()
        {
            var result = _QuestionController.Index(_TestData[1].Object.Id, false) as ViewResult;

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(List<Question>));

            var data = (List<Question>)result.ViewData.Model;

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionListPresentation));
            var model = (ATest.Models.QuestionListPresentation)result.ViewData.Model;
            Assert.AreEqual(_TestData[1].Object.Questions.Count, model.Count);
            Assert.AreEqual(_TestData[1].Object, model.Test);
        }

        [TestMethod]
        public void Index_WithValidTestId_AndAjaxRequest_Returns_View()
        {
            var tmp = _QuestionController.Index(_TestData[1].Object.Id, true);
            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(PartialViewResult));
            var result = (PartialViewResult)tmp;

            Assert.IsNotNull(result);
            Assert.AreEqual("Ajax_Index", result.ViewName);

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionListPresentation));
            var model = (ATest.Models.QuestionListPresentation)result.ViewData.Model;
            Assert.AreEqual(_TestData[1].Object.Questions.Count, model.Count);
            Assert.AreEqual(_TestData[1].Object, model.Test);
        }

        [TestMethod]
        public void Details_WithInValidId_Returns_NotFoundView()
        {
            var result = _QuestionController.Details(int.MaxValue, _TestData[1].Object.Id, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Details_WithInValidTestId_Returns_NotFoundView()
        {
            var result = _QuestionController.Details(_QuestionData[1].Object.Id, int.MaxValue, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Details_WithMisMatchingIds_Returns_NotFoundView()
        {
            var result = _QuestionController.Details(_QuestionData[1].Object.Id, int.MaxValue, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Details_WithValidIds_Returns_View()
        {
            var result = _QuestionController.Details(_QuestionData[1].Object.Id, _QuestionData[1].Object.TestId, false) as ViewResult;

            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ViewData.Model);

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.AreEqual(_QuestionData[1].Object, model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);

        }

        [TestMethod]
        public void Details_WithValidIds_AndAjax_Returns_PartialView()
        {
            var tmp = _QuestionController.Details(_QuestionData[1].Object.Id, _QuestionData[1].Object.TestId, true);
            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(PartialViewResult));

            var result = (PartialViewResult)tmp;
            Assert.AreEqual("Ajax_Details", result.ViewName);
            
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.AreEqual(_QuestionData[1].Object, model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);
        }

        [TestMethod]
        public void Edit_WithInValidId_Returns_NotFoundView()
        {
            var result = _QuestionController.Edit(int.MaxValue, _TestData[1].Object.Id, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Edit_WithInValidTestId_Returns_NotFoundView()
        {
            var result = _QuestionController.Edit(_QuestionData[1].Object.Id, int.MaxValue, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Edit_WithMisMatchingIds_Returns_NotFoundView()
        {
            var result = _QuestionController.Edit(_QuestionData[1].Object.Id, int.MaxValue, false) as ViewResult;

            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void Edit_WithValidIds_Returns_View()
        {
            var result = _QuestionController.Edit(_QuestionData[1].Object.Id, _QuestionData[1].Object.TestId, false) as ViewResult;

            Assert.IsNotNull(result);

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.AreEqual(_QuestionData[1].Object, model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);

        }

        [TestMethod]
        public void Edit_WithValidIds_AndAjax_Returns_PartialView()
        {
            var tmp = _QuestionController.Edit(_QuestionData[1].Object.Id, _QuestionData[1].Object.TestId, true);
            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(PartialViewResult));

            var result = (PartialViewResult)tmp;
            Assert.AreEqual("Ajax_Edit", result.ViewName);

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.AreEqual(_QuestionData[1].Object, model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);
        }

        [TestMethod]
        public void Create_WithInValidTestId_Returns_NotFound()
        {
            var tmp = _QuestionController.Create(int.MaxValue, false);

            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(ViewResult));

            var result = (ViewResult)tmp;
            Assert.AreEqual("NotFound", result.ViewName);

        }

        [TestMethod]
        public void Create_WithValidTestId_Returns_View()
        {
            var tmp = _QuestionController.Create(_TestData[1].Object.Id, false);

            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(ViewResult));

            var result = (ViewResult)tmp;

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.IsNull(model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);

        }

        [TestMethod]
        public void Create_WithValidTestId_AndAjax_Returns_PartialView()
        {
            _MockHttpRequest.SetAjax(true);
            var tmp = _QuestionController.Create(_TestData[1].Object.Id, true);

            Assert.IsNotNull(tmp);
            Assert.IsInstanceOfType(tmp, typeof(PartialViewResult));

            var result = (PartialViewResult)tmp;
            Assert.AreEqual("Ajax_Create", result.ViewName);

            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(ATest.Models.QuestionPresentation));
            var model = (ATest.Models.QuestionPresentation)result.ViewData.Model;
            Assert.IsNull(model.Question);
            Assert.AreEqual(_QuestionData[1].Object.Test, model.Test);

        }

        /*[TestMethod]
        public void Create_Post_WithInValidTestId_Returns_NotFoundView()
        {
            _MockHttpRequest.EnsureForm();

            _QuestionRepository.Setup(x => x.SaveChanges()).Throws(new Bll.Errors.ValidationException());

            var tmp = _QuestionController.Create(_TestData[1].Object.Id, "Question 1", "<p>test</p>", false);

        }*/
    }
}
